package com.mapforge.map.tools.undo.tilelayeredit;

import java.awt.Point;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.swing.ImageIcon;

import com.mapforge.map.Tile;
import com.mapforge.map.TileLayer;
import com.mapforge.map.tools.tilewriting.AbstractTileWriterTool;
import com.mapforge.map.tools.tilewriting.TileWriterToolState;
import com.mapforge.map.tools.undo.TilePoint;
import com.mapforge.selection.Selection;

/**
 * This class represents edits which are nonlinear. NonRectangularLayerEdits
 * should be constructed before the actual edit has taken place in order to
 * store the state of the tiles within the area being edited.
 * 
 * @author Will Morrison
 * 
 */
public class NonRectangularLayerEdit extends AbstractTileLayerEdit {
	/**
	 * Tiles overwritten by edit
	 */
	private List<TilePoint> oldTiles;
	/**
	 * Tool used to perform this edit.
	 */
	private AbstractTileWriterTool tool;
	/**
	 * State the editing tool was in when edit occurred.
	 */
	private TileWriterToolState state;

	/**
	 * Constructs a new undoable/redoable edit. Instances should be constructed
	 * before the tile writing tool has performed its edit.
	 * 
	 * @param state
	 * @param layer
	 * @param tool
	 * @param tileSelectionArea
	 * @param icon
	 * @param description
	 */
	public NonRectangularLayerEdit(TileWriterToolState state, TileLayer layer,
			AbstractTileWriterTool tool, Selection tileSelectionArea,
			ImageIcon icon, String description) {
		super(icon, description, layer);
		// Save the points within the tools selection
		oldTiles = new ArrayList<TilePoint>();
		Iterator<? extends Point> it = tileSelectionArea.iterator();
		Point p;
		while (it.hasNext()) {
			p = it.next();
			System.out.println(p.x+" "+p.y);
			oldTiles.add(new TilePoint(layer.getTileAt(p.x, p.y), p.x, p.y));
		}
		this.tool = tool;
		this.state = state;
	}

	@Override
	public void redo() {
		tool.performEdit(state);
	}

	@Override
	public void undo() {
		Tile[][] data = getTileLayer().getData();
		TilePoint point;
		for (int i = 0; i < oldTiles.size(); i++) {
			point = oldTiles.get(i);
			data[point.y][point.x] = point.tile;
		}
	}

	@Override
	public void die() {
		oldTiles = null;
		this.setTileLayer(null);
		state = null;
		tool = null;
	}
}
